package jmine.tec.di.scope;

import java.util.HashMap;
import java.util.Map;

import jmine.tec.di.type.TypeConverter;
import jmine.tec.di.type.TypeConvertionException;
import jmine.tec.di.type.TypeConvertionSystem;

/**
 * TypedScope implementado como um mapa.
 * 
 * @author takeshi
 */
public class DefaultTypedScope extends AbstractTypedScope {

    private final Map<String, Object> local = new HashMap<String, Object>();

    private final TypeConvertionSystem typeConvertion;

    /**
     * C'tor
     * 
     * @param typeConvertion o sistema de conversao de tipos a ser usado
     * @param local o mapa local
     */
    public DefaultTypedScope(TypeConvertionSystem typeConvertion, Map<String, Object> local) {
        super();
        this.local.putAll(local);
        this.typeConvertion = typeConvertion;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean localContainsKey(String key) {
        return this.local.containsKey(key);
    }

    /**
     * Devolve o valor, convertendo tipos usando o sistema de conversao de tipos passado no construtor
     * <p>
     * {@inheritDoc}
     */
    @Override
    protected Object localGet(String key, Class<?> type) {
        Object raw = this.local.get(key);
        if (type.isInstance(raw)) {
            return raw;
        }
        TypeConverter<?> converter = this.typeConvertion.lookup(type);
        if (converter != null) {
            try {
                return converter.convert(String.valueOf(raw), type);
            } catch (TypeConvertionException e) {
                // ignore type convertion error
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public void put(String key, Object value) {
        this.local.put(key, value);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected Map<String, Object> getLocalProperties() {
        return this.local;
    }

}
